#include "ScriptSystem.hpp"
#include "SLB.hpp"
#include "GameWorld.hpp"
#include "ScriptGameObject.hpp"

using namespace Typhoon;

ScriptSystem* ScriptSystem::System = 0;

ScriptSystem::ScriptSystem() {
	if (world) {
		world->AddSystem(this);
	}

	System = this;
}

ScriptSystem::~ScriptSystem() {
	if (world) {
		world->RemoveSystem(this);
	}
}

void ScriptSystem::AddComponentFromScript(ScriptComponent* component) {
	ScriptComponent::IndexToReturn = component->GetId();
	AddComponent<ScriptComponent>();
}

void ScriptSystem::SetWorld(GameWorld* world) {
	ScriptSystem::world = world;
}

GameWorld* ScriptSystem::world = 0;

int class__index(lua_State *L)
{
	SLB_DEBUG_CALL;
	SLB_DEBUG(2, "Test __index metamethod & getCache");
	SLB::ClassInfo *c = SLB::Manager::defaultManager()->getClass(L,1);
	if (c)
	{
		c->getCache(L);
	}
	else
	{
		luaL_error(L, "Invalid class at #1");
	}
	return 1;
}


int class__newindex(lua_State *L)
{
	SLB_DEBUG_CALL;
	SLB_DEBUG(2, "Test __newindex metamethod & setCache");
	SLB::ClassInfo *c = SLB::Manager::defaultManager()->getClass(L,1);


	if (c)
	{
		c->setCache(L);
	}
	else
	{
		luaL_error(L, "Invalid class at #1");
	}
	return 0;
}

ScriptGameObject* ScriptSystem::GetObject(float ind) {
	int index = (int)ind;
	if (index<0 || index>=scriptObjects.size()) return 0;
	return scriptObjects[index];
}

int ScriptSystem::Count() {
	int size = scriptObjects.size();
	return size;
}

void ScriptSystem::InitScripting() {

	SLB::Class<GameSystem::GameObjects> ("ObjectCollection")
	.constructor()
	.iterator("iterator", &GameSystem::GameObjects::begin, &GameSystem::GameObjects::end )
	;

	SLB::Class<ScriptSystem>("System")
		.constructor()
		.set("AddComponent", &ScriptSystem::AddComponentFromScript)
		.class__index( &class__index )
		.class__newindex( &class__newindex )
		.object__index( &class__index )
		.object__newindex( &class__newindex )
		//.iterator<GameSystem, GameSystem::GameObjects::iterator>("GameObjects", &GameSystem::GameObjects::begin, &GameSystem::GameObjects::end )
		.set("Count", &ScriptSystem::Count)
		.set("GetObject", &ScriptSystem::GetObject)
		.iterator("Objects", &ScriptGameObjects::begin, &ScriptGameObjects::end)
		;
}

const char* ScriptSystem::get(const char* key) {
	return "";
}

void ScriptSystem::set(const char* k, ScriptSystem* v) {

}

void ScriptSystem::GameObjectAdded(GameObject* gameObject) {
	scriptObjects.push_back((ScriptGameObject*)gameObject->Data);
}

void ScriptSystem::GameObjectRemoved(GameObject* gameObject) {
	ScriptGameObject* so = (ScriptGameObject*)gameObject->Data;
	ScriptGameObjects::iterator it = find(scriptObjects.begin(), scriptObjects.end(), so);
	if (it==scriptObjects.end()) return;
	scriptObjects.erase(it);
}